const lodash = require('lodash')

import { funcFns } from '@/puppeteer/utils/funtion'
const loginFns = require('../common/login')
import { pageFns } from '../utils/pageHelper'

import { SourceDao } from '@/dao/sourceDao'
import { ArticleDao } from '@/dao/articleDao'
import { ArticleStatus } from '@/entities/Constant'

const SELECTORS = { "THUMB_LIST": [".detail-next-slick-list .main-item", ".image-list > .image-list-slider > .main-item"], "MORE": ".main-index .arrow-link-right", "IMAGE_VIEW": [".main-index .image-view  img"], "VIDEO_VIEW": ["#main-video .react-dove-container video"], "PRODUCT_TITLE": [".main-screen > .product-title > h1", ".module_title > .product-title-container > h1"], "ATTRIBUTE_ITEM": { "LIST": [".structure-table .structure-row", ".attribute-list .attribute-item"], "LEFT": [".col-left", ".left"], "RIGHT": [".col-right span", ".right span"] }, "PRICE_ITEM": [".price-list > .price-item > .price", ".price-list > .price-range > .price"] }
async function crawleProduct(source, folderPath, page, selectors) {
  try {
    let result = await pageFns.runResetTimout(
      source.link,
      page,
      async (link, page) => {
        await page.goto(link, { waitUntil: 'networkidle2' })
        return { err: null }
      },
      { page: page, timeout: 60000 }
    )
    if (result.err) {
      return result
    }
    /**
     * @description Crawle item list
     */
    result = await pageFns.deepRetry(
      selectors.THUMB_LIST,
      page,
      async (selector, page) => {
        await page.waitForSelector(selector)
        return { list: await page.$$(selector), selector: selector }
      },
      { page: page, timeout: 1000 }
    )
    if (result.err) {
      return result
    }
    /**
     * @description List item and get big item
     */
    let srcArray = [],
      index = 0
    for (let item of result.data.list) {
      if (index == 0) {
        await item.click()
        await pageFns.delay(2 * 1000)
      } else {
        if (index == 4) {
          await item.click()
          await pageFns.delay(2 * 1000)
          await result.data.list[3].click()
          await pageFns.delay(2 * 1000)
        }
        await page.click(selectors.MORE)
      }
      index++
      let ei = await item.$('.react-dove-playButton')
      if (ei) {
        let result = await pageFns.deepRetry(
          selectors.VIDEO_VIEW,
          page,
          async (selector, page) => {
            await page.waitForSelector(selector)
            return await pageFns.attributeName(page, selector, 'src')
          },
          { page: page }
        )
        if (!result.err) {
          srcArray.push(result.data)
        }
      } else {
        const result = await pageFns.deepRetry(
          selectors.IMAGE_VIEW,
          page,
          async (selector, page) => {
            await page.waitForSelector(selector)
            return await pageFns.attributeName(page, selector, 'src')
          },
          { page: page }
        )
        if (!result.err) {
          srcArray.push(result.data)
        }
      }
    }
    /**
     * @description start to download file
     */
    for (let i = 0; i < srcArray.length; i++) {
      let src = srcArray[i]
      await funcFns.downloadFileWithFileName(src, folderPath, i)
    }
    console.log('finish downloading...', srcArray.length, srcArray)
    /**
     * @description get product title
     */
    result = await pageFns.deepRetry(
      selectors.PRODUCT_TITLE,
      page,
      async (selector, page) => {
        await page.waitForSelector(selector)
        return await pageFns.getText(page, selector)
      },
      { page: page, timeout: 500 }
    )
    if (result.err) {
      return result
    }
    let content = { title: result.data, priceItems: [], attributeItems: {} }
    let article = {
      id: 0,
      title: result.data,
      link: source.link,
      sourceId: source.id,
      platformId: source.platform,
      status: ArticleStatus.Gather,
    }
    /**
     * @description 获取Attributes
     */
    result = await pageFns.deepRetry(
      selectors.ATTRIBUTE_ITEM.LIST,
      page,
      async (selector, page) => {
        await page.waitForSelector(selector)
        return await page.$$(selector)
      },
      { page: page, timeout: 500 }
    )
    if (result.err) {
      return result
    }
    for (let item of result.data) {
      let leftContent = await pageFns.deepRetry(
        selectors.ATTRIBUTE_ITEM.LEFT,
        item,
        async (selector, item) => {
          let content = await item.$eval(selector, (node) => node.innerText)
          if (!content) {
            throw new Error('找不到内容:' + selector)
          }
          return content
        },
        { page: page, timeout: 500 }
      )
      let rightContent = await pageFns.deepRetry(
        selectors.ATTRIBUTE_ITEM.RIGHT,
        item,
        async (selector, item) => {
          let content = await item.$eval(selector, (node) => node.innerText)
          if (!content) {
            throw new Error('找不到内容:' + selector)
          }
          return content
        },
        { page: page, timeout: 500 }
      )
      console.log('data:', leftContent.data, rightContent.data)
      content.attributeItems[leftContent.data] = rightContent.data
    }
    /**
     * @description get product price
     */
    const priceItems = await pageFns.deepRetry(
      selectors.PRICE_ITEM,
      page,
      async (selector, page) => {
        await page.waitForSelector(selector)
        return await page.$$(selector)
      },
      { page: page, timeout: 500 }
    )
    for (let priceItem of priceItems.data) {
      let price = await page.evaluate(
        (element) => element.textContent,
        priceItem
      )
      content.priceItems.push(price)
    }
    article.content = JSON.stringify(content)
    let id = await ArticleDao.save(article)
    if (!id) {
      return { err: 'ArticleDao保存失败', data: article }
    }
    article.id = id
    return { err: null, data: article }
  } catch (err) {
    return { err: err, data: null }
  }
}

const LOGINS = {}

async function goSpider(page, task, source, rule) {
  let selectors = JSON.parse(rule.codeRule)
  if (lodash.isEmpty(selectors)) {
    return { err: 'there is not selectors of source:' + JSON.stringify(source) }
  }
  try {
    //是否需要登录
    if (task.accountId) {
      let res = await loginFns.checkLogin(page, task, LOGINS)
      if (res.err) {
        console.log('goSpider.checkLogin', res)
        return res
      }
    }
    return await crawleProduct(
      source,
      SourceDao.folderPath(source),
      page,
      selectors
    )
  } catch (err) {
    return { err: err }
  }
}

export { goSpider }
